﻿/*
-----------------------------------------------------------------------------
This source file is part of Cell Cloud.

Copyright (c) 2009-2012 Cell Cloud Team - cellcloudproject@gmail.com

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/

#ifndef CellTalkService_h
#define CellTalkService_h

#include "CellPrerequisites.h"
#include "CellSingleton.h"
#include "CellService.h"
#include "CellInet4Address.h"
#include "CellInet6Address.h"
#include "CellTalkSessionContext.h"
#include "CellTalkServiceFlashAddon.h"
#include "CellTalkProxy.h"
#include "CellTalkServiceProfile.h"
#include "CellDialect.h"
#include "CellActionDelegateWorker.h"
#include "CellExecutorListener.h"

namespace cell
{
/** \addtogroup Core
 *  @{
 */
/** \addtogroup General
 *  @{
 */

class TalkAcceptorHandler;
class TalkServiceDaemon;

/** 服务交互会话服务。
@author
	Jiangwei Xu
*/
class _CellExport TalkService : public Singleton<TalkService>,
	public Service, public ExecutorListener, public GeneralAlloc
{
public:
	/** 构造函数。
	*/
	TalkService(CloudGraph* cloudGraph);

	/** 析构函数。
	*/
	virtual ~TalkService(void);

public:
	/** 启动服务。
	*/
	bool startup(void);

	/** 关闭服务。
	*/
	void shutdown(void);

	/** 是否已经执行服务器启动。
	*/
	bool prepared(void);

	/** 将 Talk 服务上锁。
	*/
	void latch(void);

	/** 将 Talk 服务解锁。
	*/
	void unlatch(void);

	/** 返回服务属性。
	*/
	TalkServiceProfile getProfile(void) const;

	/** 指定服务绑定端口。
	*/
	void setPort(uint16 port);

	/** 返回服务端口。
	*/
	uint16 getPort(void) const;

	/** 导入代理地址列表。
	*/
	void importProxyAddress(const Inet4AddressList& addressList);

	/** 开启网络通信代理服务。
	*/
	void startProxy(void);

	/** 关闭网络通信代理服务。
	*/
	void stopProxy(void);

	/** 激活 Web 服务器。
	*/
	bool activateWebService(void);

	/** 禁用 Web 服务器。
	*/
	void deactivateWebService(void);

	/** 启动维护计划。
	*/
	void startSchedule(void);

	/** 停止维护计划。
	*/
	void stopSchedule(void);

	/** 申请 Cellet 服务。
	*/
	bool call(const Inet4Address& address, const String& identifier);

	/** 挂断 Cellet 服务。
	*/
	void hangup(const String& identifier);

	/** 指定的 Cellet 服务是否已经就绪。
	*/
	bool isReady(const String& identifier);

	/** 是否已经申请了指定的 Cellet 。
	*/
	bool hasCalled(const String& identifier);

	/** 与服务节点的 Cellet 进行原语会话。
	*/
	bool talk(const String& identifier, Primitive& primitive);

	/** 与服务节点的 Cellet 进行方言会话。
	*/
	bool talk(const String& identifier, Dialect& dialect);

	/** 添加会话监听器。
	*/
	void addListener(TalkListener* listener);

	/** 移除会话监听器。
	*/
	void removeListener(TalkListener* listener);

protected:
	/** 会话身份证书。
	*/
	class _CellPrivate Certificate : public GeneralAlloc
	{
	public:
		Certificate(void);
		virtual ~Certificate(void);

	public:
		String key;			/// 密钥
		String plaintext;	/// 明文
		uint64 time;		/// 时间戳
		bool checked;		/// 是否已经发送校验请求
	};

	/** 返回标签对应的 Session。
	如果该标签未请求任何 Cellet 服务则返回 NULL 值。
	*/
	Session* getSession(const String& tag) const;

	/** 请求 Cellet 服务。
	*/
	TalkTracker* requestCellet(Session* session, const String& tag, const String& identifier);

	/** 进行 Cellet 对话。
	*/
	void dialogueCellet(Session* session, const String& tag, const Primitive& primitive);

	/** 向终端发送原语。
	*/
	bool notice(const String& tag, Primitive& primitive);

	/** 打开 Session 进入验证流程。
	*/
	void openSession(Session* session);

	/** 关闭 Session 终止连接。
	*/
	void closeSession(Session* session);

	/**
	*/
	Certificate* getCertificate(Session* session);

	/** 同意 Session 为合法 Session 。
	*/
	void acceptSession(Session* session);

	/** 拒绝指定 Session 的请求。
	*/
	void rejectSession(Session* session);

	/**
	*/
	void destroyContext(TalkSessionContext* context);

	/**
	*/
	void updateSessionTickTime(Session* session);

	/**
	*/
	void startupAddons(void);

	/**
	*/
	void shutdownAddons(void);

	/**
	*/
	bool configProxy(Session* session);

	/**
	*/
	bool isProxyMode(void) const;

	/**
	*/
	TalkProxy* getProxy(void);

	/**
	*/
	void retrySpeaker(Speaker* speaker);

	/** 执行动作。
	*/
	void doAction(ActionDelegate* delegate, ActionDialect* dialect);

	/**
	*/
	void fireListenerDialogue(const String& tag, const Primitive& primitive);
	/**
	*/
	void fireListenerContacted(const String& tag);
	/**
	*/
	void fireListenerQuitted(const String& tag);
	/**
	*/
	void fireListenerFailed(const String& identifier);

private:
	/**
	*/
	void prepared(Runnable* command);

	/**
	*/
	void executed(Runnable* command);

private:
	//-------- NODE/GATE 模式 - BEGIN --------

	typedef HashMap<Session*, Certificate*> SessionCertificates;
	typedef HashMap<Session*, TalkSessionContext*> SessionContexts;
	typedef HashMap<String, Session*> TagSessionMap;
	typedef std::vector<TalkSessionContext*> SessionContextList;

	CloudGraph* mCloudGraph;

	MessageAcceptor* mAcceptor;
	TalkAcceptorHandler* mAcceptorHandler;
	uint16 mPort;

	CELL_MUTEX(mSessionMutex);

	// 合法 Session 映射表
	SessionContexts mSessionContexts;
	// 待检验 Session
	SessionCertificates mUnidentifiedSessions;
	// 过期上下文
	SessionContextList mExpiredContexts;

	TagSessionMap mTagSessionMap;

	FlashAddon* mFlashAddon;

	// Web 服务
	TalkWebService* mWebService;

	// 代理
	TalkProxy* mProxy;

	//-------- NODE/GATE 模式 - END --------

	//-------- CONSUMER 模式 - BEGIN --------

	typedef HashMap<String, Speaker*> Speakers;
	typedef std::list<TalkListener*> ListenerList;

	String mActiveIdentifier;
	CELL_MUTEX(mSpeakerMutex);
	Speakers mSpeakers;
	Speakers mLostSpeakers;
	bool mSpeakClosed;

	CELL_MUTEX(mListenerMutex);
	ListenerList mListeners;

	ExecutorService* mExecutor;

	//-------- CONSUMER 模式 - END --------

	//-------- 共有属性 - BEGIN --------

	FileExpress* mFileExpressServer;

	TalkServiceDaemon* mDaemon;
	uint64 mTick;

	//-------- 共有属性 - END --------

public:
	/**
	*/
	static TalkService& getSingleton(void);

	/**
	*/
	static TalkService* getSingletonPtr(void);

	friend class Cellet;
	friend class Speaker;
	friend class TalkAcceptorHandler;
	friend class TalkServiceDaemon;
	friend class TalkCheckCommand;
	friend class TalkRequestCelletCommand;
	friend class TalkDialogueCelletCommand;
	friend class TalkProxyCommand;
	friend class TalkHeartbeatCommand;
	friend class ActionDialect;
};

/** @} */
/** @} */
} // end namespace cell

#endif // CellTalkService_h
